home *** CD-ROM | disk | FTP | other *** search
- /*
- * DETECT UDP SP00FiNG ON OUR FREEBSD BOX VIA KLD
- * ----------------------------------------------
- *
- * This is a partial porting of my linux lkm to detect spoofing from our box..
- * to another system....
- *
- * This kld detects only UDP Spoofing. Other implementations are possible
- * changing pru_send function of the protocol you are interested in... You
- * can use this kld to understand how to do that on another protocol or you
- * can write me for other implementations.
- *
- * Set MY_IP, MY_SECOND_IP with your address/es...
- *
- * This kld modifies a function of udp pr_usrreqs structure... other **bsd
- * systems have a function to interface socket routines with protocols.
- *
- * Notes: TCP implementation is possible via kld
- * IGMP & ICMP are also possible but they use pru_send in common
- * so check inp->inp_ip_p for IPPROTO_IGMP, IPPROTO_ICMP and so
- * on...
- *
- * idea & code by pIGpEN [pigpen@s0ftpj.org, deadhead@sikurezza.org]
- *
- * s0ftpr0ject - digital security for y2k
- * www.s0ftpj.org
- *
- * sikurezza.org - italian security mailing list
- * www.sikurezza.org
- *
- */
-
- /*
- * pay attention: this code is compatible only with new kernels with
- * for example jail support... so you have to change pru_send to have
- * it working on old versions.
- *
- * uname -a
- *
- * FreeBSD storpio.cameretta.pig 4.0-19990705-CURRENT FreeBSD 4.0-19990705-
- * CURRENT #4 ..... i386
- *
- * If you wanna a porting of this code and you have no time to do that
- * write to me at: deadhead@sikurezza.org with subject "PORTING A KLD"
- *
- */
-
- #define MY_IP "192.168.1.2"
- #define MY_SECOND_IP "192.168.1.2"
- /* my machine has only an ip address and no other eth# or ip aliases */
- #define LOOPBACK "127.0.0.1"
- #define DONT_PASS
-
- #include <sys/param.h>
- #include <sys/systm.h>
- #include <sys/malloc.h>
- #include <sys/mbuf.h>
- #include <sys/kernel.h>
- #include <sys/proc.h>
- #include <sys/socket.h>
- #include <sys/socketvar.h>
- #include <sys/sysctl.h>
- #include <sys/syslog.h>
- #include <sys/protosw.h>
- #include <net/if.h>
- #include <net/route.h>
- #include <netinet/in.h>
- #include <netinet/in_systm.h>
- #include <netinet/in_pcb.h>
- #include <netinet/ip.h>
- #include <netinet/ip_var.h>
- #include <netinet/ip_icmp.h>
- #include <netinet/udp.h>
- #include <netinet/udp_var.h>
-
-
- extern struct protosw inetsw[];
- extern struct udpstat udpstat;
- static int udpcksum = 1;
-
-
- static int s_load __P((struct module *, int, void *));
-
- static int udp_send __P((struct socket * , int ,
- struct mbuf *, struct sockaddr *,
- struct mbuf *, struct proc *));
-
- static int (*old_udp_send) __P((struct socket * , int ,
- struct mbuf *, struct sockaddr *,
- struct mbuf *, struct proc *));
-
- static int udp_output __P((struct inpcb *, struct mbuf *,
- struct sockaddr *, struct mbuf *,
- struct proc *));
-
- static u_int32_t inaton __P((const char *));
-
-
- /* ipfw macro... inet_ntoa() also works well from here it's the same thing */
-
- #define print_ip(a) printf("%d.%d.%d.%d", \
- (int)(ntohl(a.s_addr) >> 24) & 0xFF, \
- (int)(ntohl(a.s_addr) >> 16) & 0xFF, \
- (int)(ntohl(a.s_addr) >> 8 ) & 0xFF, \
- (int)(ntohl(a.s_addr)) & 0xFF);
-
- static int
- s_load (struct module *module, int cmd, void *arg)
- {
- int s;
-
- switch(cmd) {
- case MOD_LOAD:
- s = splnet();
- old_udp_send = inetsw[ip_protox[IPPROTO_UDP]].pr_usrreqs->pru_send;
- inetsw[ip_protox[IPPROTO_UDP]].pr_usrreqs->pru_send = udp_send;
- splx(s);
- break;
-
- case MOD_UNLOAD:
- s = splnet();
- inetsw[ip_protox[IPPROTO_UDP]].pr_usrreqs->pru_send = old_udp_send;
- splx(s);
- break;
- }
-
- return 0;
- }
-
- static moduledata_t s_mod_1 = {
- "udp_mod",
- s_load,
- 0
- };
-
- DECLARE_MODULE(udp_mod, s_mod_1, SI_SUB_PSEUDO, SI_ORDER_ANY);
-
-
- static int
- udp_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *addr,
- struct mbuf *control, struct proc *p)
- {
- struct inpcb *inp;
-
- inp = sotoinpcb(so);
- if (inp == 0) {
- m_freem(m);
- return EINVAL;
- }
- return udp_output(inp, m, addr, control, p);
- }
-
-
- static int
- udp_output(inp, m, addr, control, p)
- register struct inpcb *inp;
- register struct mbuf *m;
- struct sockaddr *addr;
- struct mbuf *control;
- struct proc *p;
- {
- register struct udpiphdr *ui;
- register int len = m->m_pkthdr.len;
- struct in_addr laddr;
- struct sockaddr_in *sin;
- int s = 0, error = 0;
-
- if (control)
- m_freem(control); /* XXX */
-
- if (len + sizeof(struct udpiphdr) > IP_MAXPACKET) {
- error = EMSGSIZE;
- goto release;
- }
-
- if (addr) {
- sin = (struct sockaddr_in *)addr;
- prison_remote_ip(p, 0, &sin->sin_addr.s_addr);
- laddr = inp->inp_laddr;
- if (inp->inp_faddr.s_addr != INADDR_ANY) {
- error = EISCONN;
- goto release;
- }
- /*
- * Must block input while temporarily connected.
- */
- s = splnet();
- error = in_pcbconnect(inp, addr, p);
- if (error) {
- splx(s);
- goto release;
- }
- } else {
- if (inp->inp_faddr.s_addr == INADDR_ANY) {
- error = ENOTCONN;
- goto release;
- }
- }
- /*
- * Calculate data length and get a mbuf
- * for UDP and IP headers.
- */
- M_PREPEND(m, sizeof(struct udpiphdr), M_DONTWAIT);
- if (m == 0) {
- error = ENOBUFS;
- if (addr)
- splx(s);
- goto release;
- }
-
- /*
- * Fill in mbuf with extended UDP header
- * and addresses and length put into network format.
- */
- ui = mtod(m, struct udpiphdr *);
- bzero(ui->ui_x1, sizeof(ui->ui_x1));
- ui->ui_pr = IPPROTO_UDP;
- ui->ui_len = htons((u_short)len + sizeof (struct udphdr));
- ui->ui_src = inp->inp_laddr;
- ui->ui_dst = inp->inp_faddr;
- ui->ui_sport = inp->inp_lport;
- ui->ui_dport = inp->inp_fport;
- ui->ui_ulen = ui->ui_len;
-
- /*
- * Stuff checksum and output datagram.
- */
- ui->ui_sum = 0;
- if (udpcksum) {
- if ((ui->ui_sum = in_cksum(m, sizeof (struct udpiphdr) + len)) == 0)
- ui->ui_sum = 0xffff;
- }
- ((struct ip *)ui)->ip_len = sizeof (struct udpiphdr) + len;
- ((struct ip *)ui)->ip_ttl = inp->inp_ip_ttl; /* XXX */
- ((struct ip *)ui)->ip_tos = inp->inp_ip_tos; /* XXX */
-
- if(ui->ui_src.s_addr != inaton(MY_IP) &&
- ui->ui_src.s_addr != inaton(MY_SECOND_IP) &&
- ui->ui_src.s_addr != inaton(LOOPBACK)) {
- printf("UDP Spoofing detected as: ");
- print_ip(ui->ui_src);
- printf(" to ");
- print_ip(ui->ui_dst);
- #ifdef DONT_PASS
- printf(" Packet not accepted to be sent\n");
- goto release;
- #endif
- }
-
- udpstat.udps_opackets++;
-
- error = ip_output(m, inp->inp_options, &inp->inp_route,
- inp->inp_socket->so_options & (SO_DONTROUTE | SO_BROADCAST),
- inp->inp_moptions);
-
- if (addr) {
- in_pcbdisconnect(inp);
- inp->inp_laddr = laddr; /* XXX rehash? */
- splx(s);
- }
- return (error);
-
- release:
- m_freem(m);
- return (error);
- }
-
- u_int32_t inaton(const char *str)
- {
- unsigned long l;
- unsigned int val;
- int i;
-
- l = 0;
-
- for(i=0; i < 4; i++) {
- l <<= 8;
- if(*str != '\0') {
- val = 0;
- while(*str != '\0' && *str != '.') {
- val *= 10;
- val += *str - '0';
- str++;
- }
- l |= val;
- if(*str != '\0')
- str++;
- }
- }
- return(htonl(l));
- }
-